#ifndef SL_MANAGERTEMPLATE_HPP
#define SL_MANAGERTEMPLATE_HPP

// std Header
#include <map>
#include <string>

// SFML Header
#include <SFML/Graphics/Shader.hpp>

// Eigene Header
#include "../System/Singleton.hpp"
#include "../System/Logger.hpp"
#include "../System/Convert.hpp"

namespace sl
{
	namespace tmp
	{
		template <class M>
		class ManagerTemplate : public Singleton<ManagerTemplate<M> >
		{
		friend class Singleton<ManagerTemplate<M> >;

		public:
			ManagerTemplate()
			{}

			virtual ~ManagerTemplate()
			{
				Clear();
			}

		protected:
			std::map<std::string, M> myData;

		public:
			virtual M* Insert(const std::string& name, const M& m)
			{
				if (myData.find(name) == myData.end())
					myData.insert(myData.begin(), std::pair<std::string, M>(name, m));

				return &myData.find(name)->second;
			}

			/*virtual M* Insert(std::string& name)
			{
				if (dynamic_cast<std::string*>(&name))
					return Insert(::sl::GetNameFromFilename(name), name);

				return NULL;
			}*/

			virtual M* Insert(const std::string& name)
			{
				if (typeid(M) == typeid(std::string))
					return Insert(::sl::GetNameFromFilename(name), *reinterpret_cast<M*>(&std::string(name)));//*dynamic_cast<M*>(&std::string(name)));

				return NULL;
			}

			virtual ManagerTemplate<M>* Delete(const std::string& name)
			{
				if (myData.find(name) != myData.end())
					myData.erase(name);

				return this;
			}

			virtual M* Get(const std::string& name)
			{
				if (myData.find(name) != myData.end())
					return &myData.find(name)->second;

				return NULL;
			}

			virtual ManagerTemplate<M>* Clear()
			{
				myData.clear();
				return this;
			}
		};

		template <class M>
		class ManagerPointer : public Singleton<ManagerPointer<M> >
		{
		friend class Singleton<ManagerPointer<M> >;

		public:
			ManagerPointer()
			{}

			virtual ~ManagerPointer()
			{
				Clear();
			}

		protected:
			std::map<std::string, M*> myData;

		public:
			virtual M* Insert(const std::string& name, M* m)
			{
				if (myData.find(name) == myData.end())
					myData.insert(myData.begin(), std::pair<std::string, M*>(name, m));

				return myData.find(name)->second;
			}

			virtual ManagerPointer<M>* Delete(const std::string& name)
			{
				if (myData.find(name) != myData.end())
					myData.erase(name);

				return this;
			}

			virtual M* Get(const std::string& name)
			{
				if (myData.find(name) != myData.end())
					return myData.find(name)->second;

				return NULL;
			}

			virtual ManagerPointer<M>* Clear()
			{
				for (std::map<std::string, M*>::iterator itor = myData.begin(); itor != myData.end(); itor++)
					delete itor->second;

				myData.clear();
				return this;
			}
		};
	}

	#define LogManager tmp::ManagerPointer<sl::Log>::GetInstance()
	#define FolderManager tmp::ManagerTemplate<std::string>::GetInstance()
	#define ShaderManager tmp::ManagerTemplate<sf::Shader>::GetInstance()

	//#define GuiManager tmp::ManagerPointer<cp::cpObject>::GetInstance()
}

#endif //SL_MANAGERTEMPLATE_HPP